#! /bin/sh /usr/share/dpatch/dpatch-run
## 81_6611_hdpvr_signal_monitor.dpatch by  <root@mythserver.home.rodriguez-vudoyra.com>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.

@DPATCH@
diff -urNad mythtv-0.22.0-fixes23003~/libs/libmythtv/analogsignalmonitor.cpp mythtv-0.22.0-fixes23003/libs/libmythtv/analogsignalmonitor.cpp
--- mythtv-0.22.0-fixes23003~/libs/libmythtv/analogsignalmonitor.cpp	2009-12-27 11:48:30.000000000 -0600
+++ mythtv-0.22.0-fixes23003/libs/libmythtv/analogsignalmonitor.cpp	2009-12-27 11:54:58.000000000 -0600
@@ -4,23 +4,116 @@
 #include <cerrno>
 #include <unistd.h>
 #include <sys/ioctl.h>
+#include <poll.h>
 
 #include "videodev_myth.h"
 #include "mythcontext.h"
 #include "analogsignalmonitor.h"
 #include "v4lchannel.h"
 
-#define LOC QString("AnalogSM: ").arg(channel->GetDevice())
-#define LOC_ERR QString("AnalogSM, Error: ").arg(channel->GetDevice())
+#define LOC QString("AnalogSM: %1 ").arg(channel->GetDevice())
+#define LOC_ERR QString("AnalogSM, Error: %1 ").arg(channel->GetDevice())
 
-AnalogSignalMonitor::AnalogSignalMonitor(
-    int db_cardnum, V4LChannel *_channel, uint64_t _flags) :
+AnalogSignalMonitor::AnalogSignalMonitor(int db_cardnum, V4LChannel *_channel,
+                                         uint64_t _flags) :
     SignalMonitor(db_cardnum, _channel, _flags),
-    usingv4l2(false)
+    m_usingv4l2(false),
+    m_stage(0)
 {
     int videofd = channel->GetFd();
     if (videofd >= 0)
-        usingv4l2 = CardUtil::hasV4L2(videofd);
+    {
+        m_usingv4l2 = CardUtil::hasV4L2(videofd);
+        CardUtil::GetV4LInfo(videofd, m_card, m_driver, m_version);
+        VERBOSE(VB_RECORD, LOC + QString("card '%1' driver '%2' version '%3'")
+                .arg(m_card).arg(m_driver).arg(m_version));
+    }
+}
+
+bool AnalogSignalMonitor::handleHDPVR(int videofd)
+{
+    struct v4l2_encoder_cmd command;
+    struct pollfd polls;
+
+    if (m_stage == 0)
+    {
+        VERBOSE(VB_RECORD, LOC + "hd-pvr start encoding");
+        // Tell it to start encoding, then wait for it to actually feed us
+        // some data.
+        memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
+        command.cmd = V4L2_ENC_CMD_START;
+        if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0)
+            m_stage = 1;
+        else
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Start encoding failed" + ENO);
+            command.cmd = V4L2_ENC_CMD_STOP;
+            ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
+        }
+    }
+
+    if (m_stage == 1)
+    {
+        VERBOSE(VB_RECORD, LOC + "hd-pvr wait for data");
+
+        polls.fd      = videofd;
+        polls.events  = POLLIN;
+        polls.revents = 0;
+
+        if (poll(&polls, 1, 1500) > 0)
+        {
+            m_stage = 2;
+            QMutexLocker locker(&statusLock);
+            signalStrength.SetValue(25);
+        }
+        else
+        {
+            VERBOSE(VB_RECORD, LOC + "Poll timed-out.  Resetting");
+            memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
+            command.cmd = V4L2_ENC_CMD_STOP;
+            ioctl(videofd, VIDIOC_ENCODER_CMD, &command);
+            m_stage = 0;
+
+            QMutexLocker locker(&statusLock);
+            signalStrength.SetValue(0);
+        }
+    }
+
+    if (m_stage == 2)
+    {
+        VERBOSE(VB_RECORD, LOC + "hd-pvr data ready.  Stop encoding");
+
+        command.cmd = V4L2_ENC_CMD_STOP;
+        if (ioctl(videofd, VIDIOC_ENCODER_CMD, &command) == 0)
+            m_stage = 3;
+        else
+        {
+            QMutexLocker locker(&statusLock);
+            signalStrength.SetValue(50);
+        }
+    }
+
+    if (m_stage == 3)
+    {
+        struct v4l2_format vfmt;
+        memset(&vfmt, 0, sizeof(vfmt));
+        vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+        VERBOSE(VB_RECORD, LOC + "hd-pvr waiting for valid resolution");
+        if ((ioctl(videofd, VIDIOC_G_FMT, &vfmt) == 0) && vfmt.fmt.pix.width)
+        {
+            VERBOSE(VB_RECORD, LOC + QString("hd-pvr resolution %1 x %2")
+                    .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
+            m_stage = 4;
+        }
+        else
+        {
+            QMutexLocker locker(&statusLock);
+            signalStrength.SetValue(75);
+        }
+    }
+
+    return (m_stage == 4);
 }
 
 void AnalogSignalMonitor::UpdateValues(void)
@@ -36,19 +129,24 @@
         return;
 
     bool isLocked = false;
-    if (usingv4l2)
+    if (m_usingv4l2)
     {
-        struct v4l2_tuner tuner;
-        bzero(&tuner, sizeof(tuner));
-
-        if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0)
-        {
-            VERBOSE(VB_IMPORTANT,
-                    LOC_ERR + "Failed to probe signal (v4l2)" + ENO);
-        }
+        if (m_driver == "hdpvr")
+            isLocked = handleHDPVR(videofd);
         else
         {
-            isLocked = tuner.signal;
+            struct v4l2_tuner tuner;
+            bzero(&tuner, sizeof(tuner));
+
+            if (ioctl(videofd, VIDIOC_G_TUNER, &tuner, 0) < 0)
+            {
+                VERBOSE(VB_IMPORTANT,
+                        LOC_ERR + "Failed to probe signal (v4l2)" + ENO);
+            }
+            else
+            {
+                isLocked = tuner.signal;
+            }
         }
     }
     else 
@@ -70,7 +168,8 @@
     {
         QMutexLocker locker(&statusLock);
         signalLock.SetValue(isLocked);
-        signalStrength.SetValue(isLocked ? 100 : 0);
+        if (isLocked)
+            signalStrength.SetValue(100);
     }
 
     EmitStatus();
diff -urNad mythtv-0.22.0-fixes23003~/libs/libmythtv/analogsignalmonitor.h mythtv-0.22.0-fixes23003/libs/libmythtv/analogsignalmonitor.h
--- mythtv-0.22.0-fixes23003~/libs/libmythtv/analogsignalmonitor.h	2009-10-14 20:32:57.000000000 -0500
+++ mythtv-0.22.0-fixes23003/libs/libmythtv/analogsignalmonitor.h	2009-12-27 11:55:44.000000000 -0600
@@ -19,7 +19,13 @@
     virtual void UpdateValues(void);
 
   private:
-    bool usingv4l2;
+    bool handleHDPVR(int videofd);
+
+    bool     m_usingv4l2;
+    QString  m_card;
+    QString  m_driver;
+    uint32_t m_version;
+    int      m_stage;
 };
 
 #endif // _ANALOG_SIGNAL_MONITOR_H_
diff -urNad mythtv-0.22.0-fixes23003~/libs/libmythtv/mpegrecorder.cpp mythtv-0.22.0-fixes23003/libs/libmythtv/mpegrecorder.cpp
--- mythtv-0.22.0-fixes23003~/libs/libmythtv/mpegrecorder.cpp	2009-10-17 02:35:09.000000000 -0500
+++ mythtv-0.22.0-fixes23003/libs/libmythtv/mpegrecorder.cpp	2009-12-27 11:59:09.000000000 -0600
@@ -1042,14 +1042,6 @@
 
     if (driver == "hdpvr")
     {
-        if (curRecording->recgroup == "LiveTV")
-        {
-            // Don't bother checking resolution, always use best bitrate
-            int maxbitrate = std::max(high_mpeg4peakbitrate,
-                                      high_mpeg4avgbitrate);
-            SetBitrate(high_mpeg4avgbitrate, maxbitrate, "LiveTV");
-        }
-
         int progNum = 1;
         MPEGStreamData *sd = new MPEGStreamData(progNum, true);
         sd->SetRecordingType(_recording_type);
@@ -1504,7 +1496,7 @@
     memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
     command.cmd = V4L2_ENC_CMD_START;
 
-    if (driver == "hdpvr" && curRecording->recgroup != "LiveTV")
+    if (driver == "hdpvr")
         HandleResolutionChanges();
 
     VERBOSE(VB_RECORD, LOC + "StartEncoding");
@@ -1613,64 +1605,6 @@
         DTVRecorder::BufferedWrite(_scratch[i]);
 }
 
-/// After a resolution change, it can take the HD-PVR a few
-/// seconds before it is usable again.
-bool MpegRecorder::WaitFor_HDPVR(void)
-{
-    struct v4l2_encoder_cmd command;
-    struct v4l2_format vfmt;
-    struct pollfd polls;
-    int    idx;
-
-    // Tell it to start encoding, then wait for it to actually feed us
-    // some data.
-    QMutexLocker locker(&start_stop_encoding_lock);
-
-    // Sleep any less than 1.5 seconds, and the HD-PVR will
-    // return the old resolution, when the resolution is changing.
-    usleep(1500 * 1000);
-
-    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
-    command.cmd = V4L2_ENC_CMD_START;
-
-    for (idx = 0; idx < 20; ++idx)
-    {
-        if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) == 0)
-            break;
-        usleep(100 * 1000);
-    }
-
-    if (idx == 20)
-        return false;
-
-    polls.fd      = readfd;
-    polls.events  = POLLIN;
-    polls.revents = 0;
-
-    if (poll(&polls, 1, 5000) <= 0)
-        return false;
-
-    // HD-PVR should now be "ready"
-    command.cmd = V4L2_ENC_CMD_STOP;
-
-    if (ioctl(readfd, VIDIOC_ENCODER_CMD, &command) < 0)
-        return false;
-
-    memset(&vfmt, 0, sizeof(vfmt));
-    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-    for (idx = 0; idx < 20; ++idx)
-    {
-        if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt))
-            return true;
-        // Typically takes 0.9 seconds after a resolution change
-        usleep(100 * 1000);
-    }
-
-    VERBOSE(VB_RECORD, LOC + "WaitForHDPVR failed");
-    return false;
-}
-
 void MpegRecorder::SetBitrate(int bitrate, int maxbitrate,
                               const QString & reason)
 {
@@ -1708,9 +1642,6 @@
     memset(&vfmt, 0, sizeof(vfmt));
     vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
             
-    if (driver == "hdpvr")
-        WaitFor_HDPVR();
-
     if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt))
     {
         VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2")
diff -urNad mythtv-0.22.0-fixes23003~/libs/libmythtv/mpegrecorder.h mythtv-0.22.0-fixes23003/libs/libmythtv/mpegrecorder.h
--- mythtv-0.22.0-fixes23003~/libs/libmythtv/mpegrecorder.h	2009-10-14 20:32:51.000000000 -0500
+++ mythtv-0.22.0-fixes23003/libs/libmythtv/mpegrecorder.h	2009-12-27 11:59:39.000000000 -0600
@@ -86,7 +86,6 @@
 
     void ResetForNewFile(void);
 
-    bool WaitFor_HDPVR(void);
     void SetBitrate(int bitrate, int maxbitrate, const QString & reason);
     void HandleResolutionChanges(void);
 
diff -urNad mythtv-0.22.0-fixes23003~/libs/libmythtv/signalmonitor.cpp mythtv-0.22.0-fixes23003/libs/libmythtv/signalmonitor.cpp
--- mythtv-0.22.0-fixes23003~/libs/libmythtv/signalmonitor.cpp	2009-12-27 11:48:30.000000000 -0600
+++ mythtv-0.22.0-fixes23003/libs/libmythtv/signalmonitor.cpp	2009-12-27 12:01:43.000000000 -0600
@@ -96,16 +96,13 @@
 #endif
 
 #ifdef USING_V4L
-#if 0 // Just use ChannelChangeMonitor for these types
-    if ((cardtype.toUpper() == "V4L") ||
-        (cardtype.toUpper() == "MPEG"))
+    if (cardtype.toUpper() == "HDPVR")
     {
         V4LChannel *chan = dynamic_cast<V4LChannel*>(channel);
         if (chan)
             signalMonitor = new AnalogSignalMonitor(db_cardnum, chan);
     }
 #endif
-#endif
 
 #ifdef USING_HDHOMERUN
     if (cardtype.toUpper() == "HDHOMERUN")
diff -urNad mythtv-0.22.0-fixes23003~/libs/libmythtv/signalmonitor.h mythtv-0.22.0-fixes23003/libs/libmythtv/signalmonitor.h
--- mythtv-0.22.0-fixes23003~/libs/libmythtv/signalmonitor.h	2009-12-27 11:48:30.000000000 -0600
+++ mythtv-0.22.0-fixes23003/libs/libmythtv/signalmonitor.h	2009-12-27 12:00:19.000000000 -0600
@@ -308,6 +308,7 @@
     return (CardUtil::IsDVBCardType(cardtype) ||
             (cardtype.toUpper() == "HDTV")      ||
             (cardtype.toUpper() == "HDHOMERUN") ||
+            (cardtype.toUpper() == "HDPVR") ||
             (cardtype.toUpper() == "FIREWIRE")  ||
             (cardtype.toUpper() == "FREEBOX"));
 }
